/**
 *  token的生成，验证，过期
 *  Created by lihao on 2018-03-24
 *  JWT （Json Web Token）
 *      1  header     头部   标记token的类型和加密算法   {‘alg’:'HS256', 'typ': 'JWT'}    Base64Url 编码组成
 *      2  payload    负载   用于在双方之间交换信息    {'sub':'123455', 'name': 'John Doe', 'admin': true} Base64Url 编码组成
 *      3  signature  签名   用于验证消息的发送者以及消息是否被篡改
 *                              ---- 规则（ HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)）
 *                              ---- 完整的JWT 是以逗号（.）分割的三段Base64编码
 * ###########################################################################################################################
 *
 *    @method  createToken   传入对象和过期时间      -----> 生成token
 *    @method  decodeToken   解析token中的数据
 *                  -----------   1
 */

let crypto = require('crypto');

// 引入全局加密配置文件
let secret = require('../conf/secret');

const token = {
    secret: secret.jwt,
    createToken: function(obj, timeout){
        // 定义头部
        const header = {
            'lag' : 'Hs256',
            'type': 'JWT'
        };
        let obj2 = {
            data:    obj,  // payload
            created: parseInt( Date.now()/1000 ),  // token的生成时间， 单位秒
            exp:     parseInt(timeout) || 24*60*60 // token的有效期   默认:有效期为1天
        };

        //base64 转化 header
        let base64Header = Buffer.from(JSON.stringify(header),"utf8").toString('base64');
        // payload信息
        let base64PayLoad = Buffer.from(JSON.stringify(obj2),"utf8").toString('base64');

        let base64Str = base64Header +'.'+ base64PayLoad
        // 添加签名，防止被篡改

        let hash = crypto.createHmac('sha256',this.secret);
            hash.update(base64Str);
        let signature = hash.digest('base64');

        // 拼接成Token

        return base64Str+'.'+signature;

    },
    decodeToken: function(token){
        let decArr = token.split('.');
        if( decArr.length<3 ){
            // token 非法
           return false
        }
        let header ={},payload ={},base64Str='';
        // 将payload json 字符串 解析为对象
        try{
            header=JSON.parse(Buffer.from(decArr[0],"base64").toString('utf8'));
            payload=JSON.parse(Buffer.from(decArr[1],"base64").toString('utf8'));
            base64Str = (decArr[0]+'.'+decArr[1]);
        } catch(e){
            return false
        }

        // 检测签名
        let hash = crypto.createHmac('sha256',this.secret);
            hash.update(base64Str);
        let checkSignature = hash.digest('base64');

        return {
            header:header,
            payload:payload,
            signature: decArr[2],
            checkSignature: checkSignature
        }
    },
    checkToken: function(token){
        let resDecode = this.decodeToken(token);
        if(!resDecode){
            return false
        }

        // 检验是否过期
        let a_t = parseInt(Date.now()/1000);
        let b_t = parseInt(resDecode.payload.created);
        let c_t = parseInt(resDecode.payload.exp);
        let expState = (a_t - b_t > c_t)?0:1;
        // 判断token是否合法
        if((resDecode.signature === resDecode.checkSignature)&&expState){
            return true
        } else {

        }
        return false
    }
}
module.exports = exports = token;